package com.axsoft.train;

import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;

import android.text.Html;
import android.util.Log;


/**
 * Train implementation
 * 
 * TODO: Implement cache via std html saving & parsing
 */
public class Train
{
	public String departTime;
	public String arriveTime;
	public String remains;
	public String direction;
	public String except;
	public String url;
	
	public boolean isNearest;
	public boolean isExpress;
	public boolean isValid;
	
	public int period;
	
	public ArrayList<String[]> stations;
	
	
	/**
	 * Fills object with the given values
	 */
	public void fillBase(String pDepartTime, String pArriveTime, String pRemains, String pUrl, boolean pNearest, boolean pExpress, int pPeriod) {
		departTime = pDepartTime;
		arriveTime = pArriveTime;
		remains = pRemains;
		url = pUrl;
		isNearest = pNearest;
		isExpress = pExpress;
		period = pPeriod;
	}
	
	/**
	 * Fill additional info by given values
	 */
	public void fillAdditional(String pDirection, String pExcept) {
		direction = pDirection;
		except = pExcept;
	}
	
	/**
	 * Parses string to fill the fields
	 */
	public void fromString(String pString, boolean pIsNearest) throws NullPointerException {
		isValid = false;
		
		int strongEnd 		= 0;
		int strongStart 	= 0;
		int directionStart 	= 0;
		int directionEnd 	= 0;
		int periodStart		= 0;
		int periodEnd 		= 0;
		
		isNearest = pIsNearest;
		if (isNearest) {
			strongStart = pString.indexOf("<strong>", 0);
			strongEnd = pString.indexOf("\n", strongStart);
			if (strongStart == -1 || strongEnd == -1)
				return;
			
			strongStart += 8;
		}
		
		isExpress = (pString.indexOf("time", strongEnd) == pString.indexOf("time b-sputnik", strongEnd));
		
		
		// URL
		
		int hrefStart = pString.indexOf("href=", strongEnd);
		int hrefEnd = pString.indexOf("\">", hrefStart);
		if (hrefStart == -1 || hrefEnd == -1)
			return;
		
		hrefStart += 6;		
		
		// Depart && Arrive time
		int departStart = hrefEnd + 2;
		int departEnd   = departStart + 5;
		
		int arriveStart = pString.indexOf("/>", departEnd);
		int arriveEnd   = arriveStart + 7;
		
		if (arriveStart == -1)
			return;
		
		arriveStart += 2;
		
		// if nearest then parse the direction, else - parse the period
		if (isNearest) 	{
			directionStart = pString.indexOf("time\">", arriveEnd);
			directionEnd   = pString.indexOf("</span>", directionStart);
			if (directionStart == -1 || directionEnd == -1)
				return;
			directionStart += 6;
		} else {
			periodStart = pString.indexOf("period\">", arriveEnd);
			periodEnd   = pString.indexOf("</em>", periodStart);
			if (periodStart == -1 || periodEnd == -1)
				return;
			
			periodStart += 8;
		}
		
		try	{
			if (isNearest) {
				remains = Html.fromHtml(pString.substring(strongStart, strongEnd)).toString();
				direction = Html.fromHtml(pString.substring(directionStart, directionEnd)).toString();
			} else {
				String sPeriod = Html.fromHtml(pString.substring(periodStart, periodEnd)).toString();
				if (sPeriod.contains(Constants.SIGN_PERIOD_WEEK))
					period = Constants.PERIOD_WEEK;
				else if (sPeriod.contains(Constants.SIGN_PERIOD_HOLIDAY))
					period = Constants.PERIOD_HOLIDAY;
				else
					period = Constants.PERIOD_DAILY;
			}
			url = Html.fromHtml(pString.substring(hrefStart, hrefEnd)).toString();
			departTime = Html.fromHtml(pString.substring(departStart, departEnd)).toString();
			arriveTime = Html.fromHtml(pString.substring(arriveStart, arriveEnd)).toString();
			
		} catch (Exception e)	{
			Log.e("Train.fromString", e.toString());
			return;
		}
		
		isValid = true;
	}
	
	
	/**
	 * Fills the object from HTML using parser
	 */
	public static List<Train> trainsFromCache(InputStreamReader pIs, boolean pIsNearest) {
		try	{
			List<Train> trains = new ArrayList<Train>();
			
			HtmlCleaner cleaner = new HtmlCleaner();
			TagNode rootNode = cleaner.clean(pIs);
			
			TagNode[] tagElements = rootNode.getElementsByName("li", true);
			List<TagNode> periodList = Constants.getTagsByClass("class", "em", "period", rootNode);
			
			int size = tagElements.length;
			for (int i = 2; i < size; i++) {
				try	{
					boolean isExpress = false;
					List<TagNode> tagList = Constants.getTagsByClass("class", "span", "time ", tagElements[i]);
					
					if (tagList == null || tagList.size() == 0)	{
						tagList = Constants.getTagsByClass("class", "span", "time b-sputnik", tagElements[i]);
						isExpress = true;
					}
					
					TagNode tagNode = tagList.get(0);
					
					String time = tagNode.getText().toString();
					String departTime = time.substring(0, 5);
					String arriveTime = time.substring(5); 
					String url = tagNode.getElementsByName("a", true)[0].getAttributeByName("href");
					String period = periodList.get(i - 2).getText().toString();
					int intPeriod;
					
					if (period.equals(Constants.SIGN_PERIOD_WEEK)) {
						intPeriod = Constants.PERIOD_WEEK;
					}
					else if (period.equals(Constants.SIGN_PERIOD_HOLIDAY)) {
						intPeriod = Constants.PERIOD_HOLIDAY;
					}
					else {
						intPeriod = Constants.PERIOD_DAILY;
					}
					
					Train train = new Train();
					train.fillBase(departTime, arriveTime, "", url, pIsNearest, isExpress, intPeriod);
					trains.add(train);
					
				} catch (Exception e) { continue; }
			}
			
			return trains;
		} catch (Exception e) {
			Log.e("Train.trainsFromCache", e.toString());
			return null;
		}
		
		
		
	}
	
	
	/**
	 * Get additional info from string
	 */
	public boolean getAdditionalInfo(String pString) {
		if (pString == null) {
			return false; // Throw exception
		}
		
		// Except stations
		int firstIndex = pString.indexOf("b-route-info", pString.indexOf("b-route-info") + 1);
		int lastIndex = pString.indexOf("</div>", firstIndex);
		if (firstIndex == -1 || lastIndex == -1) {
			except = null;
		} else {
			firstIndex += 15;
			except = pString.substring(firstIndex, lastIndex).trim();
		}
		
		// Get the stations
		stations = new ArrayList<String[]>();
		
		while (true) {
			firstIndex = pString.indexOf("directions\">", firstIndex);
			lastIndex  = pString.indexOf("</a>", firstIndex);
			
			if (firstIndex == -1 || lastIndex == -1) {
				break;
			}
			
			firstIndex += 12;
			
			String[] tempString = new String[2];
			
			try {
				tempString[0] = pString.substring(firstIndex, lastIndex).trim().replace("&nbsp;", "");
				
				firstIndex = lastIndex + 4;
				lastIndex = pString.indexOf("</h4>", firstIndex);
				if (lastIndex == -1)
					break;
				tempString[1] = pString.substring(firstIndex, lastIndex).trim().replace("&nbsp;", "");
				stations.add(tempString);
			} catch (Exception e) {
				Log.e("Train.getAdditionalInfo", e.toString());
				break;
			}
		}
		
		return true;
	}
	
	
	/**
	 * Fill the fields from a cache string
	 */
	public void fromCacheString(String pString) {
		isValid = false;
		if (pString == null) {
			return;
		}
		
		try {
			String values[] = pString.split("::");
			if (values == null || values.length != 7)
				return;
			
			isExpress = Boolean.parseBoolean(values[0]);
			departTime = values[1];
			arriveTime = values[2];
			direction = values[3];
			url = values[4];
			except = values[6];
			period = Integer.parseInt(values[5]);
			
		} catch (NumberFormatException e) {
			period = Constants.PERIOD_DAILY;
			isValid = true;
			return;
		}
		catch (Exception e) {
			Log.e("Train.fromCacheString", e.toString());
			return;
		}
		
		isValid = true;
	}
	
	
	/**
	 * To the cache string
	 */
	public String toCacheString() {
		String string;
		string = String.valueOf(isExpress) + "::";
		string += departTime + "::" + arriveTime + "::" + direction + "::";
		string += url + "::";
		string += String.valueOf(period) + "::";
		string += ((except == null) ? "" : except) + "\n"; 
		return string;
	}
	
	
}